package site.yunnong.atvris.portal.aspect;

import com.google.gson.Gson;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import site.yunnong.atvris.common.utils.HttpContextUtils;
import site.yunnong.atvris.common.utils.IPUtils;
import site.yunnong.atvris.dao.domain.SysLog;
import site.yunnong.atvris.dao.domain.User;
import site.yunnong.atvris.service.SysLogService;
import site.yunnong.atvris.service.domain.UmsUserDetails;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @author zjh
 * @date 2021/7/22 23:19
 */
@Aspect
@Component
public class SysLogAspect {
    
    @Resource
    private SysLogService sysLogService;

    @Pointcut("execution(public * site.yunnong.atvris.*.controller.*.*(..))")
    public void sysLog() {

    }

    @Before("sysLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {

    }

    @AfterReturning(value = "sysLog()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {

    }

    @Around("sysLog()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 执行方法
        Object result = point.proceed();
        // 执行时长
        long time = System.currentTimeMillis() - beginTime;

        // 保存日志
        saveSysLog(point, time);

        return result;
    }

    private void saveSysLog(ProceedingJoinPoint point, long time) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        SysLog sysLog = new SysLog();
        if (method.isAnnotationPresent(ApiOperation.class)) {
            ApiOperation operation = method.getAnnotation(ApiOperation.class);
            sysLog.setOperation(operation.value());
        }
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getMethod().getName();
        sysLog.setMethod(className + "." + methodName + "()");
        Object[] args = point.getArgs();
        try {
            String params = new Gson().toJson(args);
            sysLog.setParams(params);
        } catch (Exception e) {
            
        }
        User user = null;
        try {
            SecurityContext ctx = SecurityContextHolder.getContext();
            Authentication auth = ctx.getAuthentication();
            UmsUserDetails userDetails = (UmsUserDetails) auth.getPrincipal();
            user = userDetails.getUser();
        } catch (Exception e) {
        }
        if (user == null) {
            sysLog.setUuid(0L);
            sysLog.setNickname("游客");
        } else {
            sysLog.setUuid(user.getUuid());
            sysLog.setNickname(user.getNickname());
        }
        
        sysLog.setIp(IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest()));
        sysLog.setTime(time);
        sysLog.setCreateDate(LocalDateTime.now());
        
        sysLogService.save(sysLog);
    }

}
